package hashtables;

import hashtables.Entries.BucketDistributionEntry;
import hashtables.Entries.Entry;
import hashtables.Entries.HashtableDistributionEntry;
import java.util.ArrayList;
import java.util.LinkedList;

/**
 * Testing the distribution
 * @author Jan, Konstantin
 */
public final class HashtableTestDistribution
{
    /**
     * Get the buckets and the number of entries in each
     * @param hashtable The hashtable
     * @return The distribution
     */
    public static LinkedList<BucketDistributionEntry> getBucketDistribution(Hashtable hashtable)
    {
        if (hashtable == null)
        {
            throw new IllegalArgumentException("getDistribution: The hashtable must be set.");
        }
        
        LinkedList<BucketDistributionEntry> bucketDistribution = new LinkedList<BucketDistributionEntry>();
        
        for (int i = 0; i < hashtable.getCapacity(); i++)
        {
            LinkedList<Entry> bucket = hashtable.getBucket(i);
            
            if (bucket != null)
            {
                bucketDistribution.add(new BucketDistributionEntry(i, bucket.size()));
            }
        }
        
        return bucketDistribution;
    }
    
    /**
     * Prints the bucket distribution
     * @param hashtable The hashtable
     */
    public static void printBucketDistribution(Hashtable hashtable)
    {
        LinkedList<BucketDistributionEntry> distribution = getBucketDistribution(hashtable);
        
        System.out.printf("\n%5s: %7s\n", "Index", "Entries");
        
        for (BucketDistributionEntry bucketDistributionEntry: distribution)
        {
            System.out.println(bucketDistributionEntry);
        }
    }
   
    /**
     * Get the entries and the count of entries
     * @param hashtable The hashtable
     * @return The distribution
     */
    public static ArrayList<HashtableDistributionEntry> getHashtableDistribution(Hashtable hashtable)
    {
        if (hashtable == null)
        {
            throw new IllegalArgumentException("getHashtableDistribution: The hashtable must be set.");
        }
        
        LinkedList<BucketDistributionEntry> bucketDistribution = getBucketDistribution(hashtable);
        ArrayList<HashtableDistributionEntry> hashtableDistribution = new ArrayList<HashtableDistributionEntry>();
        
        for (BucketDistributionEntry bucketDistributionEntry: bucketDistribution)
        {
            int index = hashtableDistribution.indexOf(new HashtableDistributionEntry(bucketDistributionEntry.getNumEntries()));
            
            if (index != -1)
            {
                hashtableDistribution.get(index).incrementCount();
            }
            else
            {
                hashtableDistribution.add(new HashtableDistributionEntry(
                    bucketDistributionEntry.getNumEntries()
                ));
            }
        }
        
        return hashtableDistribution;
    }
    
    /**
     * Prints the hashtable distribution
     * @param hashtable The hashtable
     */
    public static void printHashtableDistribution(Hashtable hashtable)
    {
        ArrayList<HashtableDistributionEntry> distribution = getHashtableDistribution(hashtable);
        
        System.out.printf("\n%7s: %5s\n", "Entries", "Count");
        
        for (HashtableDistributionEntry hashtableDistributionEntry: distribution)
        {
            System.out.println(hashtableDistributionEntry);
        }
    }
}
